/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.nfe;

import br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub;
import br.inf.portalfiscal.www.nfe.wsdl.nferetrecepcao2.NfeRetRecepcao2Stub;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.commons.httpclient.protocol.Protocol;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * <p>Title: T2Ti ERP</p>
 * <p>Description: Classe que realiza o envio da NF-e.</p>
 *
 * <p>The MIT License</p>
 *
 * <p>Copyright: Copyright (C) 2010 T2Ti.COM</p>
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 *       The author may be contacted at:
 *           t2ti.com@gmail.com</p>
 *
 * @author Claudio de Barros (T2Ti.COM)
 * @version 1.0
 */
public class EnviaNfe {

    public Map enviaNfe(String xml, String caminhoCertificado, char[] senha) {
        try {
            String codigoUf = "50";
            String versaoDados = "2.00";
            String url = "https://homologacao.nfe.ms.gov.br/homologacao/services2/NfeRecepcao2";

            //busca os dados do certificado digital
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(new FileInputStream(caminhoCertificado), senha);
            String alias = ks.aliases().nextElement();
            X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);
            PrivateKey privatekey = (PrivateKey) ks.getKey(alias, senha);
            SocketFactoryDinamico socketFactory = new SocketFactoryDinamico(certificate, privatekey);
            //arquivo que contém a cadeia de certificados do serviço a ser consumido
            socketFactory.setFileCacerts(this.getClass().getResourceAsStream("/br/inf/portalfiscal/nfe/jssecacerts"));

            //define o protocolo a ser utilizado na conexão
            Protocol protocol = new Protocol("https", socketFactory, 443);
            Protocol.registerProtocol("https", protocol);

            OMElement omElement = AXIOMUtil.stringToOM(xml);

            NfeRecepcao2Stub.NfeDadosMsg dadosMsg = new NfeRecepcao2Stub.NfeDadosMsg();
            dadosMsg.setExtraElement(omElement);

            NfeRecepcao2Stub.NfeCabecMsg cabecMsg = new NfeRecepcao2Stub.NfeCabecMsg();
            cabecMsg.setCUF(codigoUf);
            cabecMsg.setVersaoDados(versaoDados);

            NfeRecepcao2Stub.NfeCabecMsgE cabecMsgE = new NfeRecepcao2Stub.NfeCabecMsgE();
            cabecMsgE.setNfeCabecMsg(cabecMsg);

            NfeRecepcao2Stub stub = new NfeRecepcao2Stub(url);

            NfeRecepcao2Stub.NfeRecepcaoLote2Result result = stub.nfeRecepcaoLote2(dadosMsg, cabecMsgE);

            //System.out.println(result.getExtraElement().toString());

            ByteArrayInputStream in = new ByteArrayInputStream(result.getExtraElement().toString().getBytes());

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            Document doc = dbf.newDocumentBuilder().parse(in);


            String recibo = "";
            NodeList nodeList = doc.getDocumentElement().getElementsByTagName("nRec");

            for (int i = 0; i < nodeList.getLength(); i++) {
                Element element = (Element) nodeList.item(i);
                recibo = element.getTextContent();
            }

            // TODO : Qual o motivo da espera no processamento? Quanto tempo é necessário?
            Thread.sleep(5000);
            
            return consultaEnvioNfe(recibo, xml);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        Map map = new HashMap();
        map.put("autorizado", false);
        map.put("resposta", "Erro ao enviar a NF-e");

        return map;
    }

    public Map consultaEnvioNfe(String numeroRecibo, String xmlEnviNfe) {
        Map map = new HashMap();
        try {
            String codigoUf = "50";
            String ambiente = "2";
            String url = "https://homologacao.nfe.ms.gov.br/homologacao/services2/NfeRecepcao2";

            String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                    + "<consReciNFe versao=\"2.00\" xmlns=\"http://www.portalfiscal.inf.br/nfe\">"
                    + "<tpAmb>" + ambiente + "</tpAmb>"
                    + "<nRec>" + numeroRecibo + "</nRec>"
                    + "</consReciNFe>";

            OMElement omeElement = AXIOMUtil.stringToOM(xml);

            NfeRetRecepcao2Stub.NfeDadosMsg dadosMsg = new NfeRetRecepcao2Stub.NfeDadosMsg();
            dadosMsg.setExtraElement(omeElement);

            NfeRetRecepcao2Stub.NfeCabecMsg cabecMsg = new NfeRetRecepcao2Stub.NfeCabecMsg();
            cabecMsg.setCUF(codigoUf);
            cabecMsg.setVersaoDados("2.00");

            NfeRetRecepcao2Stub.NfeCabecMsgE cabecMsgE = new NfeRetRecepcao2Stub.NfeCabecMsgE();
            cabecMsgE.setNfeCabecMsg(cabecMsg);

            NfeRetRecepcao2Stub stub = new NfeRetRecepcao2Stub(url);

            NfeRetRecepcao2Stub.NfeRetRecepcao2Result result = stub.nfeRetRecepcao2(dadosMsg, cabecMsgE);

            //System.out.println(result.getExtraElement().toString());

            ByteArrayInputStream in = new ByteArrayInputStream(result.getExtraElement().toString().getBytes());
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            Document docResposta = dbf.newDocumentBuilder().parse(in);

            NodeList nodeListMotivo = docResposta.getDocumentElement().getElementsByTagName("xMotivo");
            NodeList nodeListProt = docResposta.getDocumentElement().getElementsByTagName("protNFe");
            String respostaSefaz = "";
            String xmlProt = "";
            String xmlProc = "";
            String xmlNfe = "";
            boolean autorizado = false;

            for (int i = 0; i < nodeListMotivo.getLength(); i++) {
                Element element = (Element) nodeListMotivo.item(i);
                respostaSefaz += element.getTextContent() + "\n";
                if (element.getTextContent().startsWith("Autorizado")) {
                    autorizado = true;
                }
            }

            map.put("autorizado", autorizado);
            map.put("resposta", respostaSefaz);

            if (autorizado) {
                TransformerFactory tf = TransformerFactory.newInstance();
                Transformer trans = tf.newTransformer();
                
                ByteArrayOutputStream outProt = new ByteArrayOutputStream();
                trans.transform(new DOMSource(nodeListProt.item(0)), new StreamResult(outProt));
                xmlProt = outProt.toString().replaceAll("<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>", "");

                ByteArrayInputStream inEnviNfe = new ByteArrayInputStream(xmlEnviNfe.getBytes());
                Document docEnviNfe = dbf.newDocumentBuilder().parse(inEnviNfe);
                ByteArrayOutputStream outNfe = new ByteArrayOutputStream();
                trans.transform(new DOMSource(docEnviNfe.getElementsByTagName("NFe").item(0)), new StreamResult(outNfe));
                xmlNfe = outNfe.toString().replaceAll("<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>", "");

                xmlProc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
                xmlProc += "<nfeProc versao=\"2.00\" xmlns=\"http://www.portalfiscal.inf.br/nfe\">";
                xmlProc += xmlNfe;
                xmlProc += xmlProt;
                xmlProc += "</nfeProc>";

                map.put("xmlProc", xmlProc);
            }

            return map;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        map.put("autorizado", false);
        map.put("resposta", "Erro ao enviar a NF-e");

        return map;
    }
}